/*
 * SrsRtuStreamCaChe.h
 *
 *  Created on: 2017年6月16日
 *      Author: liutingting
 */

#ifndef PLAYER_NETWORK_SRSRTUSTREAMCACHE_H_
#define PLAYER_NETWORK_SRSRTUSTREAMCACHE_H_

#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "rtmp/srs_kernel_utility.hpp"
#include "rtmp/srs_rtu_stack.hpp"
#include "rtmp/srs_kernel_flv.hpp"

#include <list>
#include <vector>
#include <string>
using namespace std;


class SrsRtuSliceNoMap;
typedef std::map<DWORD, SrsRtuSliceNoMap*>::iterator  message_no_iterator;
typedef std::map<DWORD , SrsRtuStreamDataPacket*>::iterator  slice_no_iterator;
typedef std::map<DWORD , SrsRtuStreamDataPacket*>::iterator  packet_no_iterator;



class SrsRtuSliceNoMap
{
private:
    SrsRtuStreamDataPacket** pkts;
private:
    int slice_sum;
    int insert_slice_num;
    int insert_payload_size;

    int64_t _start_time;

    DWORD _message_no;
    int64_t	_timestamp;

    DWORD head_packetno;
    DWORD last_packetno;

public:
    SrsRtuSliceNoMap(int init_count);
    SrsRtuSliceNoMap(int64_t time_now, int sum, DWORD first_packet_no, DWORD message_no, DWORD timestamp, int id);
    virtual ~SrsRtuSliceNoMap();
public:
    int initialize(int sum, DWORD first_packet_no, DWORD message_no, DWORD timestamp, int id);
public:
    int64_t start_time();
public:
    bool insert(SrsRtuStreamDataPacket* packet);
public:
    int get_size();
    int get_insert_payload_size();
    bool is_existing(int slice_no);
public:
    void clear();
    int rbegin_packetno();
public:
    bool check_is_complete();
    int  get_loss_packet_num();
    int get_slice_sum();
public:
    int get_head_packetno();
    int get_last_packetno();
public:
    DWORD get_messageno();
    int64_t get_timestamp();

public:
    SrsRtuStreamDataPacket*	get_packet(int slice_no);
};


/**
 * @brief The SrsRtuMemoryManger class
 */
class SrsRtuMemoryManger
{
public:
    std::list<SrsRtuSliceNoMap*> queue;
    int count;
    int _size;
public:
    SrsRtuMemoryManger();
    ~SrsRtuMemoryManger();
public:
    virtual int initialize();
public:
    void push(SrsRtuSliceNoMap*);
    SrsRtuSliceNoMap* pop();
public:
    void add();
public:
    void clear();
};


/**
 * @brief The SrsRtuMessageNoMap class
 */
class SrsRtuMessageNoMap
{
private:
    std::map<DWORD , SrsRtuSliceNoMap*> messageno_map;
    std::map<DWORD , SrsRtuStreamDataPacket*>  packetno_map;
    std::map<DWORD , SrsRtuStreamDataPacket*>  video_rtns_map;

    std::map<DWORD , SrsRtuStreamDataPacket*>  audio_rtns_map;
private:
    DWORD max_packet_no;
    DWORD min_packet_no;
    int insert_payload_size;
    DWORD old_messageno;
    uint64_t last_timestamp;
    DWORD video_min_packetno;
    DWORD audio_min_packetno;



public:
    SrsRtuMessageNoMap();
    virtual ~SrsRtuMessageNoMap();
public:
    bool push(SrsRtuStreamDataPacket* packet);
    SrsRtuSliceNoMap* pop();
public:
    int get_size();
    int get_insert_payload_size();
public:
    message_no_iterator begin();
    message_no_iterator end();
    void erase_begin();
    void erase(message_no_iterator iter);
    void erase_packetno_map(DWORD min_packet_no);
    void erase_video_packetno_map(DWORD last_packet_no);
    void erase_audio_packetno_map(DWORD last_packet_no);
    void clear();
public:
    void get_loss_packetno_list(std::vector<DWORD> &packetno_list);
    void get_loss_packetno_list(std::vector<DWORD> &video_packetno_list, std::vector<DWORD> &audio_packetno_list);
public:
    DWORD get_min_packetno();
    int get_max_packetno();
    int get_packet_num();
public:
    bool check_is_complete();
    bool check_is_complete(int message_no);
    DWORD get_cache_time();
public:
    int64_t get_message_interval_timestamp();
public:
    bool get_is_output_flag();
public:
    int  get_next_message_packetno(int message_no);

public:
    int  memory_recovery(SrsRtuSliceNoMap* sliceno_map);
};




/**
 * @brief The SrsRtuCaChe class
 */
class SrsRtuStreamCaChe
{
public:
    SrsRtuStreamCaChe();
    ~SrsRtuStreamCaChe();

   //for cache data
private:
    /**
    * cache video_sh audio_sh medata_sh
    */
    SrsRtuMessageNoMap*  cache_sh;

    /**
    * cache stream packet
    */
    SrsRtuMessageNoMap*  cache_media;

private:
    bool sh_full_flag;
    bool process_packet_flag;
    bool check_sh_full_flag;
    int64_t sh_check_time;
    int64_t packet_check_time;

    //recv interface
public:
    void packet_push(SrsRtuStreamDataPacket* packet);
    void rtns_packet_push(SrsRtuStreamDataPacket* packet);

    // retransmission algorithm interface
public:
    void get_loss_packetno_list(std::vector<DWORD> &packetno_list);
    void get_loss_packetno_list(std::vector<DWORD> &video_packetno_list, std::vector<DWORD> &audio_packetno_list);
private:
    int process_rtns_sh_packet(std::vector<DWORD> &packetno_list);
    int process_rtns_stream_packet(std::vector<DWORD> &packetno_list);
    int process_rtns_stream_packet(std::vector<DWORD> &video_packetno_list, std::vector<DWORD> &audio_packetno_list);

    //rtu to rtmp  interface
private:
    int64_t first_play_time;
    int cache_min_size;
private:
    void rtu_to_rtmp();
public:
    SrsCommonMessage*  get_complete_msg();
private:
    bool get_is_output_flag();
private:
    SrsRtuSliceNoMap* get_group_slice_data();
public:
    bool erase_timeout_incomplete_slice();
private:
    SrsCommonMessage* packets_to_msg(SrsRtuSliceNoMap* sliceno_queue);
    DWORD last_audio_packetno;
    int loss_audio_packet_count;
    DWORD max_audio_packetno;
    DWORD min_audio_packetno;
    DWORD max_video_packetno;
private:
    int  memory_recovery(SrsRtuSliceNoMap* sliceno_map);

    //calculate packet loss rate info
private:
    int64_t start_statistics_time;
    int64_t rtns_start_time;
    DWORD max_packetno ;
    DWORD min_packetno;
    int recv_packet_num;
    int rtns_packet_num;
    int sh_num;
    double packet_loss_rate;
    double rtns_packet_loss_rate;
private:

private:
    void calculate_max_and_min_packetno(SrsRtuStreamDataPacket* packet);
    void calculate_packet_loss_rate();
    void calculate_rtns_packet_loss_rate();
    void calculate_video_standstill_rate();
public:
    double get_packet_loss_rate();
private:
public:
    double get_three_mins_packet_loss_rate();
    double get_three_mins_audio_packet_loss_rate();
    double get_three_mins_video_packet_loss_rate();
    double get_average_packet_loss_rate();

    //stream info
private:
    std::string url;
    int stream_id;
public:
    void set_url(std::string url);
    void set_stream_id(int stream_id);

private:
    //stream cache param
private:
    int64_t cache_time;  //ms
    int cache_stream_size;  //kbps
    int64_t rtns_check_period; //ms
    int rtns_level;
    int round_trip_time;
    int64_t calculate_rtns_level_period;
public:
    int64_t cache_output_time;
    int64_t output_timeout;
    int64_t force_output_time;
    int64_t cache_output_waittime;
    int64_t cache_no_data_time;
    bool wait_cache_flag;
    bool update_output_time_flag;
    int64_t nagle_cache_time;
    int nagle_cache_size;
public:
    void init_cache_param(int64_t delay_time, int32_t byterate);
    int set_rtns_level();
    int get_rtns_level();
    int get_cache_size();

private:
    int64_t insert_rtmp_total_size;
    int insert_rtmp_second_size;
    int64_t del_rtmp_total_size;
    int del_rtmp_second_size;
    int64_t statistics_time;
};

#endif /* PLAYER_NETWORK_SRSRTUSTREAMCACHE_H_ */
